package com.tarena.demo.luban.all.main.consumer;

import com.tarena.demo.luban.all.main.service.OrderService;
import com.tarena.demo.luban.commons.exception.BusinessDemoException;
import com.tarena.demo.luban.protocol.order.param.OrderAddParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
@RocketMQMessageListener(topic="luban-order-topic",consumerGroup = "order-group")
public class OrderAddConsumer implements RocketMQListener<OrderAddParam> {
    @Autowired
    private OrderService orderService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public void onMessage(OrderAddParam message) {
        //从redisTemplate 获取操作String类型命令子对象ValueOperation
        ValueOperations<String, String> opsForValue =
                redisTemplate.opsForValue();
        //1. 设计 当前订单数据的锁 key值 和value
        String lockKey="add:order:lock:"+message.getOrderSn();
        String valueUuid= UUID.randomUUID().toString();
        //2. 抢锁 setnx key value | expire key 10s
        Boolean tryLock =
                opsForValue.setIfAbsent
                (lockKey, valueUuid, 10, TimeUnit.SECONDS);
        try{
            //判断 是否抢到锁
            while(!tryLock){
                //没抢到 思考:有没有必要一直等待 一直抢 等待最多2次,第三次直接停止退出
                Thread.sleep(5000);
                tryLock = opsForValue.setIfAbsent(lockKey, valueUuid, 10, TimeUnit.SECONDS);
            }
            //3.只要tryLock==true 执行业务
            orderService.addOrder(message);
        }catch (BusinessDemoException e){
            log.error("新增订单失败,信息:{}",e.getMessage(),e);
        }catch (InterruptedException e){
            log.error("新增订单失败,信息:{}",e.getMessage(),e);
        }finally {
            //4.释放锁 先读取锁的key值 get lockKey | del lockKey
            String value = opsForValue.get(lockKey);
            if (valueUuid.equals(value)){
                redisTemplate.delete(lockKey);
            }
        }
    }
}
